/*
大体测试，需要自己手动把db表清除再运行才通过
*/

#include <string>
#include "libevent_cpp/include/include_all.h"
#include "svr_util/include/su_mgr.h"
#include "svr_util/include/single_progress.h"
#include "svr_util/include/read_cfg.h"
#include "svr_util/include/unit_test.h"
#include "db_driver.h"
#include "dbTableDef.h"
#include "../com/cfg.h"

using namespace std;
using namespace su;
using namespace proto;
using namespace lc;
using namespace proto;


namespace
{
	bool g_playerRev = false;
	enum State
	{
		WAIT_CONNECT,
		WAIT_DROP_TABLE, //删除上次测试的table
		WAIT_INSERT,
		WAIT_UPDATE,
		WAIT_GET,
		WAIT_DEL,
		WAIT_SQL_INSERT,
		WAIT_GET_SQL_INSERT,
		WAIT_SQL_DEL,
	};
	State m_state;

	 void OnCon();
	 void Start();
	 void StartInitTable();

	 void OnCon();

	void Insert();
	void OnQuery2(bool, const Player2 & data);

	void Start()
	{
		m_state = WAIT_CONNECT;
		UNIT_INFO("connect %s %d", CfgMgr::Ins().dbproxy_svr_ip.c_str(), CfgMgr::Ins().dbproxy_svr_port);
		Dbproxy::Ins().Init(CfgMgr::Ins().dbproxy_svr_ip, CfgMgr::Ins().dbproxy_svr_port, OnCon);

	}
	bool g_RevQueryMoreEmpty = false;
	int g_RevQueryMoreCnt = 0;
	void OnCon()
	{
		UNIT_INFO("--onCon");
		UNIT_INFO("Insert");
		m_state = WAIT_INSERT;


		{
			Player2 data;
			data.id2 = 1;
			data.myblob = "a";
			data.myblob2 = "a看到了";
			data.ride.id = 1;
			data.ride.name = "abc";
			Ride ride;
			ride.id = 1;
			ride.ids.push_back(11);
			data.ride.rides.push_back(ride);
			data.vec8.push_back(1);

			//map
			data.m1[1] = 1;
			ride.id = 32;
			data.m2[32] = ride;

			{
				auto f = [](bool isOk)
				{
					UNIT_ASSERT(WAIT_INSERT == m_state);
					UNIT_ASSERT(isOk);
				};
				Dbproxy::Ins().Del(data);
				Dbproxy::Ins().Insert(data, f);
				UNIT_INFO("------end rpc insert");
			}
			{
				auto f = [](const string& str)
				{
					Player2 player;
					bool ret = TableCfg::Ins().UnpackForObj(player, str);
					UNIT_INFO("OnQuery2");
					OnQuery2(ret, player);
				};
				Dbproxy::Ins().QueryCondRaw(data.TableId(), "id2 = 1", f);
			}

			{
				auto f = [](const string& str)
				{
					UNIT_INFO("On QueryCondPartly");
					Player2 player;
					bool ret = TableCfg::Ins().UnpackForObj(player, str);
					UNIT_ASSERT(ret);
					UNIT_ASSERT(player.id2 == 0);
					UNIT_ASSERT(player.myblob == "a");
					UNIT_ASSERT(player.myblob2 == "");
					UNIT_ASSERT(player.ride.id == 1);
					UNIT_ASSERT(player.ride.name == "abc");
					UNIT_ASSERT(player.ride.rides.size() == 1);
					UNIT_ASSERT(player.ride.rides[0].id == 1);
					UNIT_ASSERT(player.ride.rides[0].ids.size() == 1);
					UNIT_ASSERT(player.ride.rides[0].ids[0] == 11);
					UNIT_ASSERT(player.vec8.size() == 0);
				};
				vector<string> vecfieldName = { "myblob", "ride" };
				Dbproxy::Ins().QueryCondPartly(data.TableId(), "id2 = 1", vecfieldName, f);
			}

		
		}
		{
			Player3 data;
			data.id = 1;
			data.id2 = 1;
			data.myblob2 = "中文";
			auto f = [](bool isOk)
			{
				UNIT_INFO("OnRspInsert3");
				UNIT_ASSERT(WAIT_INSERT == m_state);
				UNIT_ASSERT(isOk);
				UNIT_INFO("start updte");
				m_state = WAIT_UPDATE;

				{
					Player3 data;
					data.id = 1;
					data.id2 = 1;
					data.myblob2 = "中文2";
					data.ride2.id = 1;
					data.ride2.id2 = 2;
					data.ride2.sub.id = 1;
					data.ride2.sub.ids.push_back(1);
					data.ride2.sub.ids.push_back(2);
					Dbproxy::Ins().Update(data);
				}
				{
					UNIT_INFO("Player 3 QueryCond");
					Player3 data;
					data.id = 1;
					auto f = [](const Player3* pdata)
					{
						g_playerRev = true;
						UNIT_INFO("player3 QueryCond rev");
						UNIT_ASSERT(pdata);
						const Player3& data = *pdata;
						UNIT_INFO("data.id=%d", data.id);
						UNIT_INFO("data.id2=%d", data.id2);
						UNIT_ASSERT(data.id2 == 1);
						UNIT_ASSERT(data.myblob1.empty());
						UNIT_ASSERT(data.myblob2 == "中文2");


						UNIT_ASSERT(data.ride2.id == 1);
						UNIT_ASSERT(data.ride2.id2 == 2);
						UNIT_ASSERT(data.ride2.sub.id == 1);
						UNIT_ASSERT(data.ride2.sub.ids[0] == 1);
						UNIT_ASSERT(data.ride2.sub.ids[1] == 2);
						UNIT_ASSERT(data.ride2.sub.ids.size() == 2);

						{
							Player3 data;
							data.id = 1;
							data.myblob2 = "ab";
							auto f = [](bool isOk)
							{
								UNIT_INFO("rev RpcDel cb");
								UNIT_ASSERT(isOk);
								{
									auto f = [](const Player3* pdata)
									{
										UNIT_ASSERT(nullptr == pdata);
										UNIT_INFO("del player 3 ok");
									};
									{
										Player3 data;
										Dbproxy::Ins().QueryCond("id = 1", f);
									}
								}
							};
							UNIT_INFO("Player3 RpcDel");
							Dbproxy::Ins().Del(data);
						}
					};
					Dbproxy::Ins().QueryCond("id = 1", f);
				}
			};

			Dbproxy::Ins().Del(data);
			Dbproxy::Ins().Insert(data, f);
			UNIT_INFO("Player 3 RpcInsert");
		}
		{
			{
				Player4 data;
				data.name = "a";
				data.idx = "中文";
				Dbproxy::Ins().Del(data);
				Dbproxy::Ins().Insert(data);
				UNIT_INFO("player4 insert a");
			} 
			{
				Player4 data;
				data.name = "b";
				data.idx = "中文2";
				Dbproxy::Ins().Del(data);
				Dbproxy::Ins().Insert(data);
				UNIT_INFO("player4 insert b");
				auto f = [](const std::string& data)
				{
						if (data.empty())
					{
						g_RevQueryMoreEmpty = true;
						return;
					}
					Player4 player;
					TableCfg::Ins().UnpackForObj(player, data);

					g_RevQueryMoreCnt++;
					UNIT_INFO("RevQueryMore name=%s", player.name.c_str());
				};
				Dbproxy::Ins().QueryCondForMore( data.TableId(), "num = 1", f, 100);
			}
		}

	}


	void OnQuery2(bool ret, const Player2 & data)
	{
		UNIT_ASSERT(ret);
		UNIT_ASSERT(data.id2 == 1);
		UNIT_ASSERT(data.myblob == "a");
		UNIT_ASSERT(data.myblob2 == "a看到了");


		UNIT_ASSERT(data.ride.id == 1);
		UNIT_ASSERT(data.ride.name == "abc");
		UNIT_ASSERT(data.ride.rides.size() == 1);
		UNIT_ASSERT(data.ride.rides[0].id == 1);
		UNIT_ASSERT(data.ride.rides[0].ids.size() == 1);
		UNIT_ASSERT(data.ride.rides[0].ids[0] == 11);
		UNIT_ASSERT(data.vec8[0] == 1);
		UNIT_ASSERT(data.vec8.size() == 1);
		
		//map
		decltype(data.m1) m1 = data.m1;
		decltype(data.m2) m2 = data.m2;
		UNIT_ASSERT(m1.size() == 1);
		UNIT_ASSERT(m1[1] == 1);
		UNIT_ASSERT(m2.size() == 1);
		UNIT_ASSERT(m2[32].id == 32);
		Ride &ride = m2[32];

		UNIT_ASSERT(ride.id == 32);
		UNIT_ASSERT(ride.ids.size() == 1);
		UNIT_ASSERT(ride.ids[0] == 11);

	}

}


void EndTest()
{
	UNIT_INFO("------test end ----------");
	UNIT_ASSERT(g_RevQueryMoreEmpty);
	UNIT_ASSERT(g_RevQueryMoreCnt == 2);
	UNIT_ASSERT(g_playerRev);
}
UNITTEST(test_mysql)
{
	//return;
	UNIT_ASSERT(CfgMgr::Ins().Init());

	Start();


}